<?php
/**
 *  Generic Abstract Model: per-row table access
 *
 *  Similar to Active Record pattern, in which the record is implemented in Item,
 *      and the data access in Action.
 *  Implement the common methods of selecting items and executing actions
 *
 */
namespace Dclub\modules\Catalog;

class Model_Tree
    extends \Yz\modules\Generic\Model_Abstract
{


    /**
     *  a name of item class (Yz_Item_Interface)
     *  @var string
     */
    protected $itemName = "Category";


    /** fetch the complete tree
     *
     *  @return Yz_Tree[node item]
     */
    public function fetchTree()
    {
        debug();

        $item = $this->selectItem();

        $action = $this->selectAction('SelectTree');
        $action
            ->assignFields($item->describe());

        $values = $action()->fetch();

        return $this->assignValues($values,$item);
    }


    /** fetch the tree starting from the top nodes down to the given depth inclusively
     *
     *  @return Yz_Tree[node item]
     */
    public function fetchTreeToDepth($depth)
    {
        debug();

        $item = $this->selectItem();

        $action = $this->selectAction('SelectTreeToDepth');
        $action
            ->setMaxDepth($depth)
            ->assignFields($item->describe());

        $values = $action()->fetch();

        return $this->assignValues($values,$item);
    }

    /** fetch a branch of the tree, from the node specified by id
     *
     *  @param int id
     *  @return Yz_Tree[node item]
     */
    public function fetchBranch($nodeId)
    {
        debug();

        $item = $this->selectItem();

        $action = $this->selectAction('SelectTreeBranch');
        $action
            ->setOriginNodeId($nodeId)
            ->assignFields($item->describe());

        $values = $action()->fetch();

        return $this->assignValues($values,$item);
    }

    /** fetch a branch of the tree starting from a top node (`type')
     *
     *  @param string $typeName
     *  @return Yz_Tree[node item]
     */
    public function fetchTypeBranchByName($typeName)
    {
        debug();

        $item = $this->selectItem();

        $action = $this->selectAction('SelectTreeBranchByType');
        $action
            ->setTypeName($typeName)
            ->assignFields($item->describe());

        $values = $action()->fetch();

        return $this->assignValues($values,$item);
    }

    /** fetch siblings of the specified node
     *
     *
     */
    public function fetchSiblings($node)
    {

    }


    /************************************
     *       Protected methods          *
     ************************************/

    protected function assignValues($values, $item)
    {
        if (null === $values) {
            $tree = new \Yz_Tree_Default();
        } else {
            $tree = \Yz_Tree_Default::fromArray(
                $values->map( function($val) use ($item) {
                    $item0 = clone $item;
                    return $item0->assignValues($val);
                })
            );
        }
        return $tree;
    }

}
